package com.quectel.mobile.controller.workorder;

import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.util.StrUtil;
import com.quectel.base.tuple.Tuples;
import com.quectel.business.common.CommonBusiness;
import com.quectel.business.common.dept.DeptPersonMsgBusiness;
import com.quectel.business.common.util.sys.SysCodeUtils;
import com.quectel.business.common.workorder.WorkOrderBusiness;
import com.quectel.constant.PushConstants;
import com.quectel.constant.core.dept.DeptPersonMsgConstants;
import com.quectel.constant.core.workorder.WorkOrderConstants;
import com.quectel.constant.core.workorder.WorkOrderLogConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.constant.global.annotation.RequirePermissions;
import com.quectel.constant.sys.SysCodeKeyConstants;
import com.quectel.core.module.dept.dto.DeptPersonDto;
import com.quectel.core.module.dept.service.DeptPersonService;
import com.quectel.core.module.workorder.dto.WorkOrderDto;
import com.quectel.core.module.workorder.dto.WorkOrderLogDto;
import com.quectel.core.module.workorder.service.WorkOrderService;
import com.quectel.mobile.constants.MobileRedisCacheConstants;
import com.quectel.mobile.controller.BaseController;
import com.quectel.mobile.util.SessionHolder;
import com.quectel.sys.module.sys.dto.SysUserDto;
import com.quectel.sys.module.sys.service.SysUserService;
import com.quectel.util.common.JacksonUtils;
import com.quectel.util.common.Page;
import com.quectel.util.common.Request;
import com.quectel.util.common.Response;
import com.quectel.util.redis.RedisUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.locks.Lock;

/**
 * @author caolu
 * @email louis.cao@quectel.com
 * @date 2021-10-19 13:06:54
 */
@RestController
@RequestMapping("workOrder")
@Tag(name = "WorkOrderController", description = "工单相关api")
public class WorkOrderController extends BaseController {

    private static final String COMMENT_LOCK = MobileRedisCacheConstants.PROJECT_NAME + "WORK_ORDER_COMMENT_LOCK:";
    @DubboReference
    private WorkOrderService workOrderService;
    @DubboReference
    private SysUserService sysUserService;
    @DubboReference
    private DeptPersonService deptPersonService;

    @Autowired
    private WorkOrderBusiness workOrderBusiness;
    @Autowired
    private DeptPersonMsgBusiness deptPersonMsgBusiness;
    @Autowired
    private CommonBusiness commonBusiness;

    /**
     * 保存
     */
    @PostMapping("submit")
    @Operation(summary = "提交报事报修，投诉建议和巡检相应的工单")
//    @RequirePermissions(values = {ResourceConstants.WORK_ORDER_REPORT})
    public Response<Object> submit(@RequestBody @Validated WorkOrderDto workOrderDto) {

        if (workOrderDto.getPictures() != null) {
            JacksonUtils.parseArray(workOrderDto.getPictures(), String.class);
        }
        if (workOrderDto.getCompletePictures() != null) {
            JacksonUtils.parseArray(workOrderDto.getCompletePictures(), String.class);
        }
        if (workOrderDto.getCommentPictures() != null) {
            JacksonUtils.parseArray(workOrderDto.getCommentPictures(), String.class);
        }

        Date nowDate = new Date();
        //填充基础数据
        workOrderDto.setCreateTime(nowDate);
        workOrderDto.setTenantId(SessionHolder.getLoginMobileUserSession().getTenantId());
        workOrderDto.setVillageId(SessionHolder.getLoginMobileUserSession().getCurrentVillageId());

        // 提交人为住户
        workOrderDto.setOrderSource(WorkOrderConstants.ORDER_SOURCE_HOUSEHOLD);
        workOrderDto.setSourceId(SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getId());


        List<WorkOrderLogDto> logs = new ArrayList<>();
        WorkOrderLogDto initLog = new WorkOrderLogDto();
        // 处理人只有管理员和员工
        initLog.setHandlerType(WorkOrderConstants.ORDER_HANDLER_TYPE_DEPT_PERSON);
        // 页面选择的处理人
        initLog.setHandlerId(workOrderDto.getHandlerId());
        initLog.setOrderStatus(WorkOrderConstants.ORDER_STATUS_INIT);
        initLog.setOrderDes(
                WorkOrderLogConstants.INIT_LOG_DESC_FUNC.apply(Tuples.of(WorkOrderConstants.ORDER_SOURCE_HOUSEHOLD, SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getName()))
        );
        initLog.setCreateTime(nowDate);
        logs.add(initLog);


        if (WorkOrderConstants.ORDER_STATUS_FORWARD.equals(workOrderDto.getStatus())) {
            DeptPersonDto deptPersonDto = deptPersonService.selectById(workOrderDto.getHandlerId());
            if (deptPersonDto == null) {
                return Response.error("员工不存在");
            }
            WorkOrderLogDto forwordLog = new WorkOrderLogDto();
            forwordLog.setHandlerType(WorkOrderConstants.ORDER_HANDLER_TYPE_DEPT_PERSON);
            forwordLog.setHandlerId(workOrderDto.getHandlerId());
            forwordLog.setOrderStatus(WorkOrderConstants.ORDER_STATUS_FORWARD);
            forwordLog.setOrderDes(
                    WorkOrderLogConstants.FORWARD_LOG_DESC_FUNC.apply(Tuples.of(WorkOrderConstants.ORDER_SOURCE_HOUSEHOLD, SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getName(),
                            WorkOrderConstants.ORDER_HANDLER_TYPE_DEPT_PERSON, deptPersonDto.getName()))
            );
            forwordLog.setCreateTime(nowDate);
            logs.add(forwordLog);

            workOrderDto.setWorkOrderLogDtoList(logs);
            //直接指派第一次处理事件就是创建时间
            workOrderDto.setFirstHandTime(workOrderDto.getCreateTime());

            Long workOrderId = workOrderService.saveOrUpdateWorkOrderAndLog(workOrderDto);


            deptPersonMsgBusiness.pushMsg(
                    new ArrayList<>(Arrays.asList(deptPersonDto)),
                    DeptPersonMsgConstants.SourceType.WORK_ORDER_MSG,
                    workOrderId,
                    null,
                    "(指派提醒)" + commonBusiness.getAddressByVillageInfo(workOrderDto) + " " +
                            workOrderBusiness.getCategoryAndType(workOrderDto)[0] + "|" + workOrderBusiness.getCategoryAndType(workOrderDto)[1] + ",详情:" + workOrderDto.getDetail(),
                    true,
                    new PushConstants.PushType[]{PushConstants.PushType.WECHAT_OFFICIAL}
            );

        } else {
            workOrderDto.setStatus(WorkOrderConstants.ORDER_STATUS_INIT);
            workOrderDto.setHandlerId(null);
            workOrderDto.setWorkOrderLogDtoList(logs);
            workOrderService.saveOrUpdateWorkOrderAndLog(workOrderDto);
        }


        return Response.ok();
    }


    /**
     * 列表
     */
    @GetMapping("list")
    @Operation(summary = "工单的分页查询列表")
    public Response<Page<WorkOrderDto>> list(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize,
            @Parameter(description = "状态逗号分割") @RequestParam(required = false) String statusesStr,
            @Parameter(description = "传入多工单类型,逗号分割") @RequestParam(required = false) String categoriesStr
    ) {

        //查询列表数据
        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        if (SessionHolder.getLoginMobileUserSession().getCurrentHousehold() == null) {
            //没有数据
            return Response.<Page<WorkOrderDto>>ok().wrap(new Page<WorkOrderDto>(request.getPageNo(), request.getPageSize(), SystemConstants.ZERO.intValue(), new ArrayList()));
        }

        if (StringUtils.isNotEmpty(request.getString("categoriesStr"))){
            request.getParams().put(WorkOrderConstants.WORK_ORDER_CATEGORIES, StrUtil.splitTrim(request.getString("categoriesStr"), ","));
        }

        if (StringUtils.isNotBlank(request.getString("statusesStr"))) {
            request.getParams().put(SystemConstants.STATUSES, StrUtil.splitTrim(request.getString("statusesStr"), ","));
        }
        request.getParams().put(LambdaUtil.getFieldName(WorkOrderDto::getOrderSource), WorkOrderConstants.ORDER_SOURCE_HOUSEHOLD.toString());
        request.getParams().put(LambdaUtil.getFieldName(WorkOrderDto::getSourceId), String.valueOf(SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getId()));

        request.getParams().put(LambdaUtil.getFieldName(WorkOrderDto::getVillageId), SessionHolder.getLoginMobileUserSession().getCurrentVillageId());

        int total = workOrderService.queryTotal(request.getParams());
        List<WorkOrderDto> list = null;
        if (total > 0) {
            list = workOrderService.queryList(request.getParams());
            for (WorkOrderDto workOrderDto : list) {
                SysUserDto sysUserDto = sysUserService.selectCacheById(workOrderDto.getHandlerId());
                if (sysUserDto != null) {
                    workOrderDto.setHandlerUsername(sysUserDto.getUsername());
                }
                workOrderDto.setStatusName(SysCodeUtils.easyToGetName(SysCodeKeyConstants.WORK_ORDER_STATUS, String.valueOf(workOrderDto.getStatus())));
            }
        } else {
            list = new ArrayList<>();
        }

        Page<WorkOrderDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
        return Response.<Page<WorkOrderDto>>ok().wrap(page);
    }

    /**
     * 信息
     */
    @GetMapping("info/{id}")
    @RequirePermissions(values = "workOrder:info")
    @Operation(summary = "查询单条工单记录")
    public Response<WorkOrderDto> info(@PathVariable("id") Long id) {


        return Response.<WorkOrderDto>ok().wrap(workOrderBusiness.selectById(id));
    }

    /**
     * 保存
     */
    @PostMapping("reportWorkOrder")
    @Operation(summary = "上报工单")
    public Response<Object> save(@RequestBody @Validated WorkOrderDto workOrderDto) {

        workOrderDto.setTenantId(SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getTenantId());
        workOrderDto.setVillageId(SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getVillageId());
        workOrderDto.setOrderSource(WorkOrderConstants.ORDER_SOURCE_HOUSEHOLD);
        workOrderDto.setSourceId(SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getId());
        workOrderDto.setCreateTime(new Date());

        workOrderService.saveOrUpdateWorkOrderAndLog(workOrderDto);

        return Response.ok();
    }

    /**
     * 保存
     */
    @PostMapping("comment")
    @Operation(summary = "工单评论")
    public Response<Object> comment(@RequestBody WorkOrderDto workOrderDto) {
        Lock spinLock = RedisUtils.getSpinLock(COMMENT_LOCK + workOrderDto.getId());
        spinLock.lock();
        try {
            WorkOrderDto dbValue = workOrderService.selectById(workOrderDto.getId());
            if (!WorkOrderConstants.ORDER_STATUS_FINISHED.equals(dbValue.getStatus())) {
                return Response.error("只能评价完成的工单");
            }
            if (!Objects.equals(dbValue.getOrderSource(), WorkOrderConstants.ORDER_SOURCE_HOUSEHOLD) &&
                    !dbValue.getSourceId().equals(SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getId())) {
                //只能评价自己的
                return Response.error("非法的数据操作");
            }

            WorkOrderDto updateObj = new WorkOrderDto();
            updateObj.setId(workOrderDto.getId());
            updateObj.setScore(workOrderDto.getScore());
            updateObj.setAppraise(workOrderDto.getAppraise());
            updateObj.setCommentPictures(workOrderDto.getCommentPictures());
            updateObj.setStatus(WorkOrderConstants.ORDER_STATUS_COMMENTED);
            updateObj.setCommentTime(new Date());
            workOrderService.updateById(updateObj);
        } finally {
            spinLock.unlock();
        }

        return Response.ok();
    }

    /**
     * 查询服务人员列表
     */
    @GetMapping("getServiceUsers")
    @Operation(summary = "查询服务人员列表")
    public Response<List<DeptPersonDto>> getServiceUsers(@Parameter(description = "查询参数") @RequestParam(required = false) String queryText) {
        Map<String, Object> params = new HashMap<>();
        //限定为当前小区
        params.put(LambdaUtil.getFieldName(DeptPersonDto::getStatus), SystemConstants.YES);
        params.put(LambdaUtil.getFieldName(DeptPersonDto::getVillageId), String.valueOf(SessionHolder.getLoginMobileUserSession().getCurrentVillageId()));
        params.put("queryText", queryText);
        List<DeptPersonDto> result = deptPersonService.queryList(params);
        result.forEach(v -> {
            v.setPassword(null);
        });
        return Response.<List<DeptPersonDto>>ok().wrap(result);
    }


}
